#pragma once

#include "byte_stream.hh"
#include "tcp_receiver_message.hh"
#include "tcp_sender_message.hh"

#include <cstdint>
#include <functional>
#include <list>
#include <memory>
#include <optional>
#include <queue>

//超时计数器
class RetransmissionTimer
{
private:
  /* data */
  uint64_t RTO_{};
  uint64_t time_passed_{};
  bool is_active_{};
public:
  RetransmissionTimer(uint64_t init_RTO_ms):RTO_(init_RTO_ms){};
  bool is_expired()const noexcept{return is_active_&&time_passed_>=RTO_;}
  bool is_active()const noexcept{return is_active_;}
  RetransmissionTimer& active()noexcept;
  RetransmissionTimer& timeout()noexcept;
  RetransmissionTimer& reset()noexcept;
  RetransmissionTimer& tick(uint64_t tick_ms)noexcept;
  //~RetransmissionTimer();
};

class TCPSender
{
public:
  /* Construct TCP sender with given default Retransmission Timeout and possible ISN */
  TCPSender( ByteStream&& input, Wrap32 isn, uint64_t initial_RTO_ms )
    : input_( std::move( input ) ), isn_( isn ), initial_RTO_ms_( initial_RTO_ms ),timer_(initial_RTO_ms)
  {}

  /* Generate an empty TCPSenderMessage */
  //产生一条不占用序号的空消息
  TCPSenderMessage make_empty_message() const;

  /* Receive and process a TCPReceiverMessage from the peer's receiver */
  //接收来自接受者的确认消息，维护接收窗口的大小
  void receive( const TCPReceiverMessage& msg );

  /* Type of the `transmit` function that the push and tick methods can use to send messages */
  using TransmitFunction = std::function<void( const TCPSenderMessage& )>;

  /* Push bytes from the outbound stream */
  //从内存字节流中读取待发送数据，尽可能填满接收窗口
  /*
    push 方法仅用于首次发送消息，发送过的所有消息都保存在一个队列中，等待重传或者确认。在发送过 FIN 报文后，
    push 方法不应再发送任何消息，报文重传由 tick 方法负责
  */
  void push( const TransmitFunction& transmit );

  /* Time has passed by the given # of milliseconds since the last time the tick() method was called */
  //根据外部传入的时间判断是否需要重传和进行拥塞控制
  void tick( uint64_t ms_since_last_tick, const TransmitFunction& transmit );

  // Accessors
  //返回待确认的字节数
  uint64_t sequence_numbers_in_flight() const;  // How many sequence numbers are outstanding?
  //返回连续重传报文的数目
  uint64_t consecutive_retransmissions() const; // How many consecutive *re*transmissions have happened?
  Writer& writer() { return input_.writer(); }
  const Writer& writer() const { return input_.writer(); }

  // Access input stream reader, but const-only (can't read from outside)
  const Reader& reader() const { return input_.reader(); }

private:
  // Variables initialized in constructor
  ByteStream input_;
  Wrap32 isn_;
  uint64_t initial_RTO_ms_;

  uint16_t wnd_{1};
  uint64_t next_seqno_{};
  uint64_t ack_seqno_{};
  bool syn_flag_{},fin_flag_{},send_syn_{},send_fin_{};//syn请求开始 fin请求结束 三次握手 四次挥手
  RetransmissionTimer timer_;
  uint64_t retranmission_cnt_{};
  uint64_t num_in_flight_{};
  std::queue<TCPSenderMessage>outstanding_byte_{};

  TCPSenderMessage message_( uint64_t seqno, std::string payload, bool SYN, bool FIN = false ) const;

};
